package com.lsh.oms.core.service.query;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.lang.Maps;
import com.lsh.oms.core.constant.Constants;
import com.lsh.oms.core.constant.LoggerConstant;
import com.lsh.oms.core.dao.order.OrderDetailDao;
import com.lsh.oms.core.dao.other.OrderShippingHeadMapper;
import com.lsh.oms.core.dao.payment.BillPaymentInfoDao;
import com.lsh.oms.core.dao.query.FindOrderByMisDao;
import com.lsh.oms.core.enums.*;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.model.order.OrderDetail;
import com.lsh.oms.core.model.order.OrderHead;
import com.lsh.oms.core.model.order.OrderShippingHeadWithBLOBs;
import com.lsh.oms.core.model.order.OrderSignHead;
import com.lsh.oms.core.model.payment.BillPaymentInfo;
import com.lsh.oms.core.model.query.*;
import com.lsh.oms.core.proxy.service.TmsProxy;
import com.lsh.oms.core.records.core.Return;
import com.lsh.oms.core.records.core.ReturnRepository;
import com.lsh.oms.core.service.other.ShippingOrderService;
import com.lsh.oms.core.service.sign.core.SignService;
import com.lsh.oms.core.service.tool.Criteria;
import com.lsh.oms.core.service.tool.Pageable;
import com.lsh.oms.core.utils.ComputeServiceUtils;
import com.lsh.oms.core.utils.LoggerUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author panxudong
 * @date 16/8/19
 */
@Component
public class FindOrderByMisService {

    private static final String IS_TMS = "tms_id";
    private static final String TMS_EXT = "ext";
    private static final String HEAD_INFO = "head_info";
    private static final String TMS_CONFIG = "config";
    private static final String ORDER_ID = "order_id";
    private static final String SHIPPING_ORDER_ID = "shipping_order_id";
    private static final String ADDRESS_INFO = "address_info";
    private static final String ORDER_TYPE = "order_type";
    private static final String IMG_LIST = "imgList";
    private static final String GIVE_INFO = "giveInfo";
    private static final String ACTIVITY_INFO = "activityInfo";
    private static final String REAL_QTY = "realQty";
    private static final String CUT_PROMOTION_MONEY = "cutPromotionMoney";
    private static final String TICKET_COUPON_PROMOTION_MONEY = "ticketCouponPromotionMoney";
    private static final String EXCLUDE_TAX_COST = "excludeTaxCost";
    private static final String TAX_COST = "taxCost";
    private static Logger logger = LoggerFactory.getLogger(FindOrderByMisService.class);
    private static String assemblyUrl;

    @Autowired
    private FindOrderByMisDao findOrderByMisDao;

    @Autowired
    private OrderShippingHeadMapper headDao;

    @Autowired
    private OrderDetailDao orderDetailDao;

    @Autowired
    private BillPaymentInfoDao billPaymentInfoDao;

    @Autowired
    private ShippingOrderService shippingOrderService;

    @Autowired
    private TmsProxy tmsProxy;

    @Resource
    private SignService signService;

    @Resource
    private ReturnRepository returns;

    @Value("${mis.img.host}")
    private String imgHost;

    @Value("${tms.host}")
    private String tmsHost;

    @Value("${assemblyUrl}")
    private String assemblyHost;

    @Value("${tmsLogName}")
    private String tmsLogName;

    private Logger tmsLog;

    private static final Map<String, String> RETURN_STATUS = Maps.newHashMap("PENDING", "待下发", "PRE_DELIVER", "待取货", "DELIVERED", "已取货", "RETURNED", "已返仓", "CHECKED", "已通过", "TERMINATED", "已完成", "CANCELED", "已取消");

    private JSONObject mapToJson(Map<String, Object> from) {
        JSONObject to = new JSONObject();
        if (from != null) {
            for (Map.Entry entry : from.entrySet()) {
                to.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
            }
        }

        return to;
    }

    private JSONObject mapToJson2(Map<String, Object> from) {
        JSONObject to = new JSONObject();
        if (from != null) {
            for (Map.Entry entry : from.entrySet()) {
                if (entry.getValue() instanceof Long) {
                    to.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
                } else {
                    to.put(String.valueOf(entry.getKey()), entry.getValue());
                }
            }
        }

        return to;
    }


    private Map<String, Object> mapToStringMap(Map<String, Object> from) {
        Map<String, Object> target = new HashMap<>();
        if (from != null) {
            for (Map.Entry entry : from.entrySet()) {
                if (entry.getValue() == null) {
                    target.put(String.valueOf(entry.getKey()), "");
                }

                if (entry.getValue() instanceof Long) {
                    target.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
                } else {
                    target.put(String.valueOf(entry.getKey()), entry.getValue());
                }
            }
        }

        return target;
    }

    private SplitList newSplitList(Set<Long> existCodes, Set<Long> notExistCodes) {
        return new FindOrderByMisService().new SplitList(existCodes, notExistCodes);
    }

    private List<Long> getExistKeys(List<Map<String, Object>> orders, Set<Long> codes, InterfaceEnum interfaceEnum) {
        Set<Long> existKeys = new HashSet<>();
        for (Map<String, Object> order : orders) {
            Long selectCode = Long.valueOf(String.valueOf(order.get(interfaceEnum.getSelectColumn())));
            if (codes.contains(selectCode)) {
                existKeys.add(Long.valueOf(String.valueOf(order.get(interfaceEnum.getCodeColumn()))));
            }
        }
        return new ArrayList<>(existKeys);
    }

    private void getAddressInfo(Map<String, Object> order, FindOrderByMisDao findOrderByMisDao) {
        if (order != null) {
            Long shippingId = Long.valueOf(String.valueOf(order.get(SHIPPING_ORDER_ID)));
            Map<String, Object> shipping = findOrderByMisDao.getDeliveryOrder(shippingId);
            if (shipping != null && !StringUtils.isBlank(String.valueOf(shipping.get(ADDRESS_INFO)))) {
                Object addressInfo = shipping.get(ADDRESS_INFO);
                JSONObject address = null;
                if (addressInfo != null) {
                    address = JSON.parseObject(addressInfo.toString());
                }

                Object extObject = order.get(TMS_EXT);
                JSONObject ext = null;
                if (extObject != null) {
                    ext = JSON.parseObject(extObject.toString());
                }

                order.put(TMS_EXT, ext);
                order.put(ADDRESS_INFO, address);
            } else {
                order.put(ADDRESS_INFO, new JSONObject());
            }
        }
    }

    private static void setExtToDetails(List<Map<String, Object>> details) {
        for (Map<String, Object> detail : details) {
            setExtToDetail(detail);
        }
    }

    private static void setExtToDetail(Map<String, Object> detail) {
        if (detail.containsKey(TMS_EXT)) {
            Object ext = detail.get(TMS_EXT);
            if (ext != null) {
                String extStr = String.valueOf(ext);
                if (!StringUtils.isBlank(extStr)) {
                    JSONObject extObject = JSONObject.parseObject(extStr);
                    for (Map.Entry entry : extObject.entrySet()) {
                        detail.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
                    }
                }
            }
        }
    }

    private static void setExtToDetails(JSONArray details) {
        Iterator iterator = details.iterator();
        while (iterator.hasNext()) {
            JSONObject detail = (JSONObject) iterator.next();
            setExtToDetail(detail);
        }
    }

    private static void setExtToDetail(JSONObject detail) {
        if (detail.containsKey(TMS_EXT)) {
            String ext = detail.getString(TMS_EXT);
            if (!StringUtils.isBlank(ext)) {
                JSONObject extObject = JSONObject.parseObject(ext);
                for (Map.Entry entry : extObject.entrySet()) {
                    detail.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
                }
            }
        }
    }

    private void setTransUidToReturn(List<Map<String, Object>> orders, FindOrderByMisDao findOrderByMisDao, InterfaceEnum interfaceEnum) {
        List<Long> shippingOrderIds = new ArrayList<>();
        Map<Long, Map<String, Object>> ordersMap = new HashMap<>();
        for (Map<String, Object> order : orders) {
            Long shippingOrderId = Long.valueOf(String.valueOf(order.get("shipping_order_id")));
            if (shippingOrderId != null) {
                shippingOrderIds.add(shippingOrderId);
                ordersMap.put(shippingOrderId, order);
            }
            order.put("wm_return", this.getMoney4Order(order, findOrderByMisDao, 1, interfaceEnum));
            order.put("ls_return", this.getMoney4Order(order, findOrderByMisDao, 2, interfaceEnum));
            order.put("wl_return", this.getMoney4Order(order, findOrderByMisDao, 3, interfaceEnum));
        }

        if (shippingOrderIds.size() > 0) {
            List<Map<String, Object>> shippingOrders = findOrderByMisDao.getDeliveryOrderList(shippingOrderIds);
            for (Map<String, Object> shippingOrder : shippingOrders) {
                Long shippingOrderId = Long.valueOf(String.valueOf(shippingOrder.get("shipping_order_id")));
                if (ordersMap.containsKey(shippingOrderId) && shippingOrder.get("trans_uid") != null &&
                        !StringUtils.isBlank(String.valueOf(shippingOrder.get("trans_uid")))) {
                    Long transUid = Long.valueOf(String.valueOf(shippingOrder.get("trans_uid")));
                    if (transUid != 0) {
                        Map<String, Object> order = ordersMap.get(shippingOrderId);
                        order.put("trans_uid", transUid);
                    }
                }
            }
        }
    }

    private String getMoney4Order(Map<String, Object> order, FindOrderByMisDao findOrderByMisDao, Integer type,
                                  InterfaceEnum interfaceEnum) {
        Long returnOrderId = Long.valueOf(String.valueOf(order.get(interfaceEnum.getCodeColumn())));
        BigDecimal money = new BigDecimal("0.00");
        if (type.intValue() == 1) {
            List<Map<String, Object>> returnSonOrders = findOrderByMisDao.getReturnOrdersByFOrderIdOrReturnOrderId(returnOrderId, 1, null, null);
            if (returnSonOrders.size() > 0) {
                Map<String, Object> sonOrder = returnSonOrders.get(0);
                if (sonOrder.get("cost_money") != null) {
                    money = money.add(new BigDecimal(String.valueOf(sonOrder.get("cost_money"))));
                }
            }

            if (order.get("is_mp") != null && Integer.parseInt(String.valueOf(order.get("is_mp"))) == 1) {
                if (order.get("cost_money") != null) {
                    money = money.add(new BigDecimal(String.valueOf(order.get("cost_money"))));
                }
            } else {
                List<Map<String, Object>> returnOrders = findOrderByMisDao.getReturnOrdersByFOrderIdOrReturnOrderId(null, 1, null, returnOrderId);
                if (returnOrders.size() > 0) {
                    Map<String, Object> returnOrder = returnOrders.get(0);
                    if (returnOrder.get("cost_money") != null) {
                        money = money.add(new BigDecimal(String.valueOf(returnOrder.get("cost_money"))));
                    }
                }
            }
        } else {
            List<Map<String, Object>> returnSonOrders = findOrderByMisDao.getReturnOrdersByFOrderIdOrReturnOrderId(returnOrderId, null, type, null);
            if (returnSonOrders.size() > 0) {
                Map<String, Object> sonOrder = returnSonOrders.get(0);
                if (type.intValue() == 2 && order.get("cost_money") != null) {
                    money = new BigDecimal(String.valueOf(sonOrder.get("cost_money")));
                } else {
                    if (order.get("money") != null) {
                        money = new BigDecimal(String.valueOf(sonOrder.get("money")));
                    }
                }
            }
        }
        return money.toString();
    }

    private void getOmsOrder4Relate(JSONArray relateOrders, MisOrderHeadForDetail misOrderHeadForDetail) {
        if (misOrderHeadForDetail == null) {
            return;
        }
        JSONObject relateOrder = new JSONObject();
        relateOrder.put("status_name", OrderStatus.getName(misOrderHeadForDetail.getOrderStatus()));
        relateOrder.put("order_id", String.valueOf(misOrderHeadForDetail.getOrderCode()));
        relateOrder.put("type", "1");
        relateOrders.add(relateOrder);
    }

    private void getShippingOrder4Relate(JSONArray relateOrders, Map<String, Object> shippingOrder) {
        if (shippingOrder == null) {
            return;
        }
        JSONObject relateShipping = new JSONObject();
        relateShipping.put("status_name", ShippingStatus.getName(Integer.parseInt(String.valueOf(shippingOrder.get("status")))));
        relateShipping.put("order_id", String.valueOf(shippingOrder.get("shipping_order_id")));
        relateShipping.put("type", "3");
        relateOrders.add(relateShipping);
    }

    private void getReceiptOrder4Relate(JSONArray relateOrders, Map<String, Object> receiptOrder) {
        if (receiptOrder == null) {
            return;
        }
        JSONObject relateReceipt = new JSONObject();
        relateReceipt.put("status_name", SignStatus.getName(Integer.parseInt(String.valueOf(receiptOrder.get("status")))));
        relateReceipt.put("order_id", String.valueOf(receiptOrder.get("receipt_order_id")));
        relateReceipt.put("type", "4");
        relateOrders.add(relateReceipt);
    }

    private void fillRelatedReturns(JSONArray collector, Long orderId) {

        Criteria criteria = new Criteria();
        criteria.add("order_id", orderId.toString());
        criteria.add("details-required", "false");
        List<Map<String, Object>> collect = ((List<Return>) returns.query(criteria, 1, 50L).getEntries())
                .stream()
                .map($ -> {
                    Map<String, Object> item = new HashMap<>();
                    item.put("order_id", $.id());
                    item.put("status_name", RETURN_STATUS.get($.status().name()));
                    item.put("type", "5");
                    item.put("occasion", $.occasion());
                    return item;
                })
                .collect(Collectors.toList());

        collector.addAll(collect);
    }


    private void getReturnOrder4Relate(JSONArray relateOrders, Map<String, Object> returnOrder) {
        if (returnOrder == null) {
            return;
        }
        JSONObject relateReturn = new JSONObject();

        relateReturn.put("status_name", ReturnStatus.getName(Integer.parseInt(String.valueOf(returnOrder.get("status")))));
        relateReturn.put("order_id", String.valueOf(returnOrder.get("return_order_id")));
        relateReturn.put("type", "5");

        relateOrders.add(relateReturn);
    }

    @PostConstruct
    private void init() {
        assemblyUrl = assemblyHost + "/cal/index/assembly";
        tmsLog = LoggerFactory.getLogger(tmsLogName);
    }

    /**
     * 获取订单列表
     *
     * @param orderCodeList
     * @return
     */
    @Transactional(readOnly = true)
    public List<MisOrderHeadForList> getOrderHeadList(List<Long> orderCodeList) {
        List<MisOrderHeadForList> misOrderHeadForListList = findOrderByMisDao.getOrderHeadList(orderCodeList);
        if (misOrderHeadForListList.size() <= 0) {
            return misOrderHeadForListList;
        }

        Map<Long, MisOrderHeadForList> misOrderHeadForListMap = new HashMap<>();
        for (MisOrderHeadForList misOrderHeadForList : misOrderHeadForListList) {
            //统计当前订单下单用户有效订单数
            misOrderHeadForList.setEffectiveOrderCount(findOrderByMisDao.getEffectiveOrderCount(misOrderHeadForList.getUserCode(),
                    OrderStatus.ORDER_CANCEL_CUSTOMER.getIndex(), OrderStatus.ORDER_CANCEL_CUSTOMERSERVICE.getIndex(),
                    OrderStatus.ORDER_CANCEL_SYSTEM.getIndex()));

            //设置售后信息
            MisOrderAftersales misOrderAftersales = findOrderByMisDao.getOrderAftersalesInfo(misOrderHeadForList.getOrderCode());
            if (misOrderAftersales != null) {
                misOrderHeadForList.setAftersalesCode(misOrderAftersales.getAftersalesCode());
                misOrderHeadForList.setAftersalesStatus(misOrderAftersales.getAftersalesStatus());
            }

            //设置物理仓库编号
            if (!StringUtils.isBlank(misOrderHeadForList.getExt())) {
                JSONObject extObject = JSONObject.parseObject(misOrderHeadForList.getExt());
                misOrderHeadForList.setWarehouseCode(extObject.getString(Constants.WAREHOUSE_CODE));
            }

            misOrderHeadForListMap.put(misOrderHeadForList.getOrderCode(), misOrderHeadForList);
        }

        List<MisOrderHeadForList> misOrderHeadForListSortList = new ArrayList<>();

        MisOrderHeadForList misOrderHeadForList;
        OrderShippingHeadWithBLOBs orderShippingHeadWithBLOBs;
        for (Long orderCode : orderCodeList) {
            // TODO redis 优化
            orderShippingHeadWithBLOBs = headDao.selectByOrderCode(orderCode);
            misOrderHeadForList = misOrderHeadForListMap.get(orderCode);
            if (orderShippingHeadWithBLOBs != null) {
                if (misOrderHeadForList == null) {
                    continue;
                }
                misOrderHeadForList.setDealTime(orderShippingHeadWithBLOBs.getCreatedAt());
            }
            misOrderHeadForListSortList.add(misOrderHeadForList);
        }

        return misOrderHeadForListSortList;
    }

    /**
     * 获取订单详情
     *
     * @param orderCode
     * @return
     */
    @Transactional(readOnly = true)
    public MisOrderHeadForDetail getOrderHead(Long orderCode) {
        MisOrderHeadForDetail misOrderHeadForDetail = findOrderByMisDao.getOrderHead(orderCode);
        if (misOrderHeadForDetail == null) {
            LoggerUtils.saveLog(" [GetOrderHead][Return Value : " + JSON.toJSONString(misOrderHeadForDetail) + "]", LoggerConstant.LOGGER_INFO);
            return null;
        }

        BillPaymentInfo filter = new BillPaymentInfo();
        filter.setBillCode(orderCode);
        filter.setPayStatus(PayStatus.PAID.getValue());
        List<MisOrderHeadForPay> misOrderHeadForPayList = billPaymentInfoDao.selectByFilter(filter);
        if (CollectionUtils.isEmpty(misOrderHeadForPayList)) {
            misOrderHeadForPayList = Collections.EMPTY_LIST;
        }
        misOrderHeadForDetail.setPaySequences(misOrderHeadForPayList);

        OrderShippingHeadWithBLOBs orderShippingHeadWithBLOBs = headDao.selectByOrderCode(orderCode);
        if (orderShippingHeadWithBLOBs != null) {
            misOrderHeadForDetail.setDealTime(orderShippingHeadWithBLOBs.getCreatedAt());
        }

        //设置仓储类型名称
        misOrderHeadForDetail.setStorageTypeName(StorageType.getName(misOrderHeadForDetail.getStorageType()));
        //根据订单ID获取对应的订单扩展信息
        MisOrderHeadExtForDetail misOrderHeadExtForDetail = findOrderByMisDao.getOrderHeadExt(misOrderHeadForDetail.getId());
        //统计当前订单下单用户有效订单数
        misOrderHeadForDetail.setEffectiveOrderCount(findOrderByMisDao.getEffectiveOrderCount(misOrderHeadForDetail.getUserCode(),
                OrderStatus.ORDER_CANCEL_CUSTOMER.getIndex(), OrderStatus.ORDER_CANCEL_CUSTOMERSERVICE.getIndex(),
                OrderStatus.ORDER_CANCEL_SYSTEM.getIndex()));

        //设置物理仓库信息
        String headExt = misOrderHeadForDetail.getExt();
        JSONObject headExtObject;
        if (StringUtils.isBlank(headExt)) {
            headExtObject = new JSONObject();
        } else {
            headExtObject = JSONObject.parseObject(headExt);
        }
        misOrderHeadForDetail.setWarehouseCode(headExtObject.getString(Constants.WAREHOUSE_CODE));

        //设置订单扩展信息
        if (misOrderHeadExtForDetail != null) {
            Date cancelDate = misOrderHeadExtForDetail.getCancelTime();
            if (cancelDate != null) {
                misOrderHeadForDetail.setCancelTime(cancelDate.getTime() / 1000);
            }
            misOrderHeadForDetail.setDelayRemark(misOrderHeadExtForDetail.getDelayRemark());
            misOrderHeadForDetail.setRemark(misOrderHeadExtForDetail.getRemarks());
            misOrderHeadForDetail.setCancelRemark(misOrderHeadExtForDetail.getCancelRemark());
            misOrderHeadForDetail.setCancelUser(misOrderHeadExtForDetail.getCancelUser());
            //mis 前端报错
            misOrderHeadForDetail.setRemarks("");

            misOrderHeadForDetail.setOriginMoney(misOrderHeadExtForDetail.getOriginMoney());

            String ext = misOrderHeadExtForDetail.getExt();
            JSONObject extObject;
            if (StringUtils.isBlank(ext)) {
                extObject = new JSONObject();
            } else {
                extObject = JSONObject.parseObject(ext);
            }

            for (Map.Entry entry : extObject.entrySet()) {
                headExtObject.put(String.valueOf(entry.getKey()), entry.getValue());
            }

            misOrderHeadForDetail.setExt(headExtObject.toJSONString());
        }

        //设置售后信息
        MisOrderAftersales misOrderAftersales = findOrderByMisDao.getOrderAftersalesInfo(misOrderHeadForDetail.getOrderCode());
        if (misOrderAftersales != null) {
            misOrderHeadForDetail.setAftersalesCode(misOrderAftersales.getAftersalesCode());
            misOrderHeadForDetail.setAftersalesStatus(misOrderAftersales.getAftersalesStatus());
        }

        //获取订单明细信息
        List<MisOrderDetailForDetail> misOrderDetailForDetailList = findOrderByMisDao.getOrderDetailList(orderCode);
        if (misOrderDetailForDetailList.size() <= 0) {
            LoggerUtils.saveLog(" [GetOrderHead][Return Value : " + JSON.toJSONString(misOrderHeadForDetail) + "]", LoggerConstant.LOGGER_INFO);
            return misOrderHeadForDetail;
        }

        Map<Long, MisOrderDetailForDetail> orderDetailMap = new HashMap<>();
        for (MisOrderDetailForDetail misOrderDetailForDetail : misOrderDetailForDetailList) {
            if (StringUtils.isBlank(misOrderDetailForDetail.getDetailExt())) {
                orderDetailMap.put(misOrderDetailForDetail.getId(), misOrderDetailForDetail);
            } else {
                JSONObject detailExtObject = JSONObject.parseObject(misOrderDetailForDetail.getDetailExt());
                misOrderDetailForDetail.setRealQty(detailExtObject.getBigDecimal(REAL_QTY));
                misOrderDetailForDetail.setImgList(detailExtObject.getString(IMG_LIST));
                misOrderDetailForDetail.setGiveInfo(detailExtObject.getString(GIVE_INFO));
                misOrderDetailForDetail.setActivityInfo(detailExtObject.getString(ACTIVITY_INFO));
                misOrderDetailForDetail.setCutPromotionMoney(detailExtObject.getBigDecimal(CUT_PROMOTION_MONEY));
                misOrderDetailForDetail.setTicketCouponPromotionMoney(detailExtObject.getBigDecimal(TICKET_COUPON_PROMOTION_MONEY));

                misOrderDetailForDetail.setExcludeTaxCost(detailExtObject.getBigDecimal(EXCLUDE_TAX_COST));
                misOrderDetailForDetail.setTaxCost(detailExtObject.getBigDecimal(TAX_COST));

                Integer isWeighingGoods = detailExtObject.getInteger("isWeighingGoods");
                if (null == isWeighingGoods) {
                    isWeighingGoods = 0;
                }
                misOrderDetailForDetail.setIsWeighingGoods(isWeighingGoods);
            }
        }

        if (!orderDetailMap.isEmpty()) {
            logger.info(" [GetOrderHead][OrderDetailMap Size : " + orderDetailMap.size());
            //获取订单明细扩展信息
            List<MisOrderDetailExtForDetail> misOrderDetailExtForDetailList = findOrderByMisDao.getOrderDetailExtList(new ArrayList<>(orderDetailMap.keySet()));

            for (MisOrderDetailExtForDetail misOrderDetailExtForDetail : misOrderDetailExtForDetailList) {
                MisOrderDetailForDetail misOrderDetailForDetail = orderDetailMap.get(misOrderDetailExtForDetail.getId());
                misOrderDetailForDetail.setGiveInfo(misOrderDetailExtForDetail.getGiveInfo());
                misOrderDetailForDetail.setImgList(misOrderDetailExtForDetail.getImgList());
                misOrderDetailForDetail.setRealQty(misOrderDetailExtForDetail.getRealQty());
                misOrderDetailForDetail.setActivityInfo(misOrderDetailExtForDetail.getActivityInfo());
                misOrderDetailForDetail.setCutPromotionMoney(misOrderDetailExtForDetail.getCutPromotionMoney());
                misOrderDetailForDetail.setTicketCouponPromotionMoney(misOrderDetailExtForDetail.getTicketCouponPromotionMoney());
            }
        }

        misOrderHeadForDetail.setMisOrderDetailForDetailList(misOrderDetailForDetailList);

        return misOrderHeadForDetail;
    }

    /**
     * 通过地址编码和用户编码获取未编辑和未提交DC状态订单
     *
     * @param addressCode
     * @param userCode
     * @return
     */
    @Transactional(readOnly = true)
    public List<OrderHead> getOrderHeadListByAddressCodeAndUserCode(Long addressCode, Long userCode) {
        List<OrderHead> orderHeadList = findOrderByMisDao.getOrderHeadListByAddressCodeAndUserCode(addressCode, userCode, OrderStatus.ORDER_NO_EDIT.getIndex(), OrderStatus.ORDER_COMMITING_OFC.getIndex());
        return orderHeadList;
    }

    /**
     * 通过地址编码和用户编码获取未编辑和未提交DC状态订单
     *
     * @param startTime
     * @param endTime
     * @return
     */
    @Transactional(readOnly = true)
    public JSONArray getOrderHeadListByTimes(Integer startTime, Integer endTime) {
        List<OrderHead> orderHeadList = findOrderByMisDao.getOrderHeadListByTimes(startTime, endTime, 2000, OrderStatus.ORDER_WM_NEW.getIndex());

        Map<String, BigDecimal> sumMap = null;
        if (orderHeadList != null && orderHeadList.size() > 0) {
            sumMap = new HashMap<>();
            OrderDetail orderDetail;
            for (OrderHead od : orderHeadList) {
                orderDetail = new OrderDetail();
                orderDetail.setOrderCode(od.getOrderCode());
                List<OrderDetail> detailList = orderDetailDao.findList(orderDetail);
                if (detailList != null && detailList.size() > 0) {
                    for (OrderDetail ol : detailList) {
                        if (ol.getSkuCode() == null || ol.getGoodsCode() == null || ol.getQuantity() == null) {
                            continue;
                        }

                        String sumKey = ol.getSkuCode() + ":" + ol.getGoodsCode();
                        if (sumMap.get(sumKey) == null) {
                            sumMap.put(sumKey, ol.getQuantity());
                        } else {
                            BigDecimal qty = sumMap.get(sumKey);
                            sumMap.put(sumKey, qty.add(ol.getQuantity()));
                        }
                    }
                }
            }
        }

        JSONArray skuQtys = new JSONArray();
        if (sumMap != null) {
            Set<Map.Entry<String, BigDecimal>> entries = sumMap.entrySet();
            JSONObject sku;
            for (Map.Entry<String, BigDecimal> entry : entries) {
                sku = new JSONObject();
                String[] sumkeys = entry.getKey().split(":");
                sku.put("skuCode", sumkeys[0]);
                sku.put("goodsCode", sumkeys[1]);
                sku.put("qty", entry.getValue());
                skuQtys.add(sku);
            }
        }

        return skuQtys;
    }

    /**
     * 通过地址编码获取除未编辑/用户取消/客服取消订单状态的订单数量
     *
     * @param addressCode
     * @return
     */
    @Transactional(readOnly = true)
    public Integer getOrderHeadCountByAddressCode(Long addressCode) {
        Integer count = findOrderByMisDao.getOrderHeadCountByAddressCode(addressCode, OrderStatus.ORDER_NO_EDIT.getIndex(),
                OrderStatus.ORDER_CANCEL_CUSTOMER.getIndex(), OrderStatus.ORDER_CANCEL_CUSTOMERSERVICE.getIndex(), null);
        return count;
    }

    /**
     * 通过地址编码获取当天的除未编辑/用户取消/客服取消订单状态的订单数量
     *
     * @param addressCode
     * @return
     */
    @Transactional(readOnly = true)
    public Integer getOrderHeadCountNowByAddressCode(Long addressCode) {
        Date date = new Date();

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        Date targetDate = calendar.getTime();
        Integer targetTime = (int) TimeUnit.MILLISECONDS.toSeconds(targetDate.getTime());

        Integer count = findOrderByMisDao.getOrderHeadCountByAddressCode(addressCode, OrderStatus.ORDER_NO_EDIT.getIndex(),
                OrderStatus.ORDER_CANCEL_CUSTOMER.getIndex(), OrderStatus.ORDER_CANCEL_CUSTOMERSERVICE.getIndex(), targetTime);
        return count;
    }

    /**
     * 通过用户码获取该用户除了未编辑/已完成/用户取消/客服取消订单状态的订单数量
     *
     * @param userCode
     * @return
     */
    @Transactional(readOnly = true)
    public Integer getNofinishOrderCountNowByUserCode(Long userCode) {
        Integer count = findOrderByMisDao.getOrderHeadCountByUserCode(userCode, OrderStatus.ORDER_NO_EDIT.getIndex(), OrderStatus.ORDER_FINISH.getIndex());
        return count;
    }

    /**
     * 查询该时间区间中的有效订单号，并且"订单状态" <= "已完成"
     *
     * @param startTime
     * @param endTime
     * @return
     */
    @Transactional(readOnly = true)
    public List<Long> getOrderCodesByTimeRange(Integer startTime, Integer endTime) {
        List<Long> orderCodes = findOrderByMisDao.getOrderCodesByTimeRange(startTime, endTime);
        if (orderCodes == null) {
            orderCodes = new ArrayList<>();
        }
        return orderCodes;
    }

    /**
     * 查询当前用户未支付的订单号
     *
     * @param uid
     * @return
     */
    @Transactional(readOnly = true)
    public List<Long> getNotPayOrderCodesByUid(Long uid) {
        List<Long> orderCodes = findOrderByMisDao.getNotPayOrderCodesByUid(uid);
        if (orderCodes == null) {
            orderCodes = new ArrayList<>();
        }
        return orderCodes;
    }

    /**
     * 通过地址编码获取除用户取消/客服取消订单状态的订单数量,最近下单时间
     *
     * @param addressCode
     * @return
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getOrderHeadCountAndTimeByAddressCode(Long addressCode) {
        Map<String, Object> resultMap = findOrderByMisDao.getOrderHeadCountAndTimeByAddressCode(addressCode,
                OrderStatus.ORDER_CANCEL_CUSTOMER.getIndex(), OrderStatus.ORDER_CANCEL_CUSTOMERSERVICE.getIndex(),
                OrderStatus.ORDER_CANCEL_SYSTEM.getIndex());
        return resultMap;
    }

    /**
     * 通过地址编码获取最近下单时间拣货订单状态的订单
     *
     * @param addressCode
     * @return
     */
    @Transactional(readOnly = true)
    public MisOrderHeadForList getOrderForAfterSales(Long addressCode) {
        MisOrderHeadForList misOrderHeadForList = findOrderByMisDao.getOrderForAfterSales(addressCode, OrderStatus.ORDER_SORTING.getIndex());
        return misOrderHeadForList;
    }

    /**
     * 获取返仓单列表
     *
     * @param codes
     * @return
     */
    @Transactional(readOnly = true)
    public List<JSONObject> getReturnOrderList(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getReturnOrderList(codes);
//        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderId);
//        JSONArray tmsArray;
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            tmsArray = JSONArray.parseArray(splitList.getTmsContent());
//        } else {
//            tmsArray = new JSONArray();
//        }
        setTransUidToReturn(orders, findOrderByMisDao, interfaceEnum);
        return this.packList(orders, codes, new JSONArray(), interfaceEnum, logSign);
    }

    /**
     * 获取发货单列表
     *
     * @param codes
     * @return
     */
    @Transactional(readOnly = true)
    public List<JSONObject> getDeliveryOrderList(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getDeliveryOrderList(codes);
//        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderId);
        JSONArray tmsArray = new JSONArray();
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            tmsArray = JSONArray.parseArray(splitList.getTmsContent());
//        } else {
//            tmsArray = new JSONArray();
//            // 多点订单，发货员信息，需要从oms_ext中解析出来
////            for (Map<String, Object> order : orders) {
//////                this.fillDeliveryInfo(order);
////            }
//        }
        return this.packList(orders, codes, tmsArray, interfaceEnum, logSign);
    }

    /**
     * 获取签收单列表
     *
     * @param codes
     * @return
     */
    @Transactional(readOnly = true)
    public List<JSONObject> getReceiptOrderList(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getReceiptOrderList(codes);

        for (Map<String, Object> receiptMap : orders) {
            Object orderIdObject = receiptMap.get("order_id");
            if (orderIdObject != null) {
                long orderId = Long.parseLong(orderIdObject.toString());
                OrderShippingHeadWithBLOBs orderShippingHeadWithBLOBs = shippingOrderService.getBolbs(orderId);
                if (orderShippingHeadWithBLOBs != null) {
                    receiptMap.put("address_info", orderShippingHeadWithBLOBs.getAddressInfo());
                    if (orderShippingHeadWithBLOBs.getArrivedAt() != null) {
                        receiptMap.put("shipping_arrived_at", orderShippingHeadWithBLOBs.getArrivedAt());
                    } else {
                        receiptMap.put("shipping_arrived_at", 0);
                    }
                }
            }
        }

        logger.info("{} orders is {}", logSign, JSON.toJSONString(orders));

//        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderId);
//        JSONArray tmsArray;
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            tmsArray = JSONArray.parseArray(splitList.getTmsContent());
//        } else {
//            tmsArray = new JSONArray();
//        }
        JSONArray tmsArray = new JSONArray();
        return this.packList(orders, codes, tmsArray, interfaceEnum, logSign);
    }

    /**
     * 获取返仓单详情
     *
     * @param code
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReturnOrder(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        Map<String, Object> order = findOrderByMisDao.getReturnOrder(code);
//        String tmsContent = this.splitOrderByIsTms(order, code, interfaceEnum, true, venderId, logSign);
//        JSONObject returnObject;
//        if (this.isTmsNull(tmsContent)) {
//            List<Map<String, Object>> details = findOrderByMisDao.getReturnOrderDetail(code);
//            this.getAddressInfo(order, findOrderByMisDao);
//            returnObject = this.packOrder(order, details, interfaceEnum, true, logSign, findOrderByMisDao, venderId);
//        } else {
//            returnObject = JSONObject.parseObject(tmsContent);
//        }
        List<Map<String, Object>> details = findOrderByMisDao.getReturnOrderDetail(code);
        this.getAddressInfo(order, findOrderByMisDao);

        return this.packOrder(order, details, interfaceEnum, true, logSign, findOrderByMisDao, venderId);
    }

    /**
     * 获取发货单详情
     *
     * @param code
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getDeliveryOrder(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        Map<String, Object> order = findOrderByMisDao.getDeliveryOrder(code);
        List<Map<String, Object>> details = findOrderByMisDao.getDeliveryOrderDetail(code);

        order.put("order_type", getOrderType(Long.valueOf(String.valueOf(order.get("order_id")))));

        return this.packOrder(order, details, interfaceEnum, true, logSign, findOrderByMisDao, venderId);
    }

    /**
     * 获取签收单详情
     *
     * @param code
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReceiptOrder(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        Map<String, Object> order = findOrderByMisDao.getReceiptOrder(code);

        List<Map<String, Object>> details = findOrderByMisDao.getReceiptOrderDetail(code);
        this.getAddressInfo(order, findOrderByMisDao);

        return this.packOrder(order, details, interfaceEnum, true, logSign, findOrderByMisDao, venderId);
    }

    @Transactional(readOnly = true)
    public JSONObject getReceiptOrder2(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        Map<String, Object> order = findOrderByMisDao.getReceiptOrder(code);
//        String tmsContent = this.splitOrderByIsTms2(order, code, interfaceEnum, true, logSign, venderId);

        List<Map<String, Object>> details = findOrderByMisDao.getReceiptOrderDetail(code);
        this.getAddressInfo(order, findOrderByMisDao);

        return this.packOrder(order, details, interfaceEnum, true, logSign, findOrderByMisDao, venderId);
    }

    /**
     * 通过订单ID获取签收单信息
     *
     * @param codes
     * @param interfaceEnum
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReceiptInfoByOrderIds(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getReceiptInfoByOrderIds(codes);
        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, true, logSign, venderId);
        List<Long> existKeys = this.getExistKeys(orders, splitList.getExistCodes(), interfaceEnum);
        List<Map<String, Object>> details;
        if (existKeys.size() > 0) {
            details = findOrderByMisDao.getReceiptOrderDetails(existKeys);
        } else {
            details = new ArrayList<>();
        }
        JSONObject returnObject = new JSONObject();
        return this.packGetInfo(orders, details, true, splitList.getExistCodes(), returnObject, interfaceEnum, logSign, venderId);
    }

    /**
     * 通过订单ID获取发货单信息
     *
     * @param codes
     * @param interfaceEnum
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getDeliveryInfoByOrderIds(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getDeliveryInfoByOrderIds(codes);
        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderId);
        List<Long> existKeys = this.getExistKeys(orders, splitList.getExistCodes(), interfaceEnum);
        List<Map<String, Object>> details;
//        logger.info("existKeys size is " + JSON.toJSONString(existKeys));
        if (existKeys.size() > 0) {
            details = findOrderByMisDao.getDeliveryOrderDetails(existKeys);
        } else {
            details = new ArrayList<>();
        }

        JSONObject returnObject = new JSONObject();
        return this.packGetInfo(orders, details, true, splitList.getExistCodes(), returnObject, interfaceEnum, logSign, venderId);
    }

    /**
     * 通过发货单ID获取签收单信息
     *
     * @param code
     * @param interfaceEnum
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReceiptByDeliveryId(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        Map<String, Object> order = findOrderByMisDao.getReceiptByDeliveryId(code);
        this.fillReceiptStatus(order, false, code);
        List<Map<String, Object>> details;
        if (order != null && order.containsKey(interfaceEnum.getCodeColumn())) {
            Long key = Long.valueOf(String.valueOf(order.get(interfaceEnum.getCodeColumn())));
            details = findOrderByMisDao.getReceiptOrderDetail(key);
        } else {
            details = new ArrayList<>();
        }

        return this.packOrder(order, details, interfaceEnum, false, logSign, null, venderId);
    }

    /**
     * 通过发货单ID获取返仓单信息
     *
     * @param code
     * @param interfaceEnum
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReturnByDeliveryId(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        Map<String, Object> order = findOrderByMisDao.getReturnByDeliveryId(code);
//        String tmsContent = this.splitOrderByIsTms(order, code, interfaceEnum, false, venderId, logSign);
//        logger.info(tmsContent);
//        JSONObject returnObject;
//        if (!this.isTmsNull(tmsContent)) {
//            returnObject = JSONObject.parseObject(tmsContent);
//        } else {
        this.fillReceiptStatus(order, true, code);
        List<Map<String, Object>> details;
        if (order != null && order.containsKey(interfaceEnum.getCodeColumn())) {
            Long key = Long.valueOf(String.valueOf(order.get(interfaceEnum.getCodeColumn())));
            details = findOrderByMisDao.getReturnOrderDetail(key);
        } else {
            details = new ArrayList<>();
        }

        return this.packOrder(order, details, interfaceEnum, false, logSign, null, venderId);
    }

    /**
     * 获取售后返仓单,head和details
     *
     * @param code
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getAfterSaleReturnOrder(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        Map<String, Object> order = findOrderByMisDao.getAfterSaleReturnByOrderId(code);
//        String tmsContent = this.splitOrderByIsTms(order, code, interfaceEnum, false, venderId, logSign);
//        JSONObject returnObject;
//        if (!this.isTmsNull(tmsContent)) {
//            returnObject = JSONObject.parseObject(tmsContent).getJSONObject("info");
//        } else {
        if (order == null) {
            return new JSONObject();
        }

        List<Map<String, Object>> details;
        if (order.containsKey(interfaceEnum.getCodeColumn())) {
            long returnOrderId = Long.parseLong(String.valueOf(order.get(interfaceEnum.getCodeColumn())));
            details = findOrderByMisDao.getReturnOrderDetail(returnOrderId);
        } else {
            details = new ArrayList<>();
        }
        order.put("details", details);

        return new JSONObject(order);
    }

    /**
     * 通过发货单ID获取发货单明细
     *
     * @param codes
     * @param interfaceEnum
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getDeliveryDetails(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> details = findOrderByMisDao.getDeliveryDetails(codes);
        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(details, codes, interfaceEnum, false, logSign, venderId);
//        JSONObject returnObject;
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            returnObject = JSONObject.parseObject(splitList.getTmsContent());
//        } else {
//            returnObject = new JSONObject();
//        }

        List<Long> existKeys = this.getExistKeys(details, splitList.getExistCodes(), interfaceEnum);
        List<Map<String, Object>> orders;
        if (existKeys.size() > 0) {
            orders = findOrderByMisDao.getDeliveryOrderList(existKeys);
        } else {
            orders = new ArrayList<>();
        }

        JSONObject returnObject = new JSONObject();
        return this.packDetails(orders, details, existKeys, returnObject, interfaceEnum, logSign, venderId);
    }

    /**
     * 通过发货单ID获取签收单信息
     *
     * @param codes
     * @param interfaceEnum
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReceiptInfoByDeliveryIds(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getReceiptInfoByDeliveryIds(codes);
        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderId);
        List<Long> existKeys = this.getExistKeys(orders, splitList.getExistCodes(), interfaceEnum);
        List<Map<String, Object>> details;
        if (existKeys.size() > 0) {
            details = findOrderByMisDao.getDeliveryOrderDetails(existKeys);
        } else {
            details = new ArrayList<>();
        }
//        JSONObject returnObject;
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            returnObject = JSONObject.parseObject(splitList.getTmsContent());
//        } else {
//            returnObject = new JSONObject();
//        }
        JSONObject returnObject = new JSONObject();
        return this.packGetInfo(orders, details, true, splitList.getExistCodes(), returnObject, interfaceEnum, logSign, venderId);
    }

    /**
     * 获取订单相关单据
     *
     * @param code
     * @param interfaceEnum
     * @param logSign
     * @return
     */
    @Transactional(readOnly = true)
    public JSONArray getRelateOrders(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        MisOrderHeadForDetail misOrderHeadForDetail = this.findOrderByMisDao.getOrderHead(code);

        JSONArray relateOrders = new JSONArray();
        this.getOmsOrder4Relate(relateOrders, misOrderHeadForDetail);
        Map<String, Object> receiptOrder = findOrderByMisDao.getReceiptByOrderId(code);
        this.getReceiptOrder4Relate(relateOrders, receiptOrder);

        fillRelatedReturns(relateOrders, code);

        Map<String, Object> shippingOrder = findOrderByMisDao.getDeliveryByOrderId(code);
        this.getShippingOrder4Relate(relateOrders, shippingOrder);

        return relateOrders;
    }

    /**
     * 通过订单ID获取返仓单头信息
     *
     * @param codes
     * @param interfaceEnum
     * @param logSign
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReturnHeadsByOrderIds(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getReturnInfoByOrderIds(codes);
        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderId);
//        JSONObject returnObject;
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            returnObject = JSONObject.parseObject(splitList.getTmsContent());
//        } else {
//            returnObject = new JSONObject();
//        }
        JSONObject returnObject = new JSONObject();
        return this.packGetInfo(orders, null, false, splitList.getExistCodes(), returnObject, interfaceEnum, logSign, venderId);
    }

    /**
     * 通过订单ID获取返仓单明细信息
     *
     * @param codes
     * @param interfaceEnum
     * @param logSign
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReturnDetailsByOrderIds(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getReturnInfoByOrderIds(codes);
        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderId);
        List<Long> existKeys = this.getExistKeys(orders, splitList.getExistCodes(), interfaceEnum);
        List<Map<String, Object>> details;
        if (existKeys.size() > 0) {
            details = findOrderByMisDao.getReturnOrderDetails(existKeys);
        } else {
            details = new ArrayList<>();
        }
//        JSONObject returnObject;
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            returnObject = JSONObject.parseObject(splitList.getTmsContent());
//        } else {
//            returnObject = new JSONObject();
//        }

        JSONObject returnObject = new JSONObject();
        return this.packDetails(orders, details, existKeys, returnObject, interfaceEnum, logSign, venderId);
    }

    /**
     * 通过发货单ID获取返仓单头信息
     *
     * @param codes
     * @param interfaceEnum
     * @param logSign
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReturnHeadsByDeliveryIds(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        List<Map<String, Object>> orders = findOrderByMisDao.getReturnInfoByShippingIds(codes);
        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderId);
//        JSONObject returnObject;
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            returnObject = JSONObject.parseObject(splitList.getTmsContent());
//        } else {
//            returnObject = new JSONObject();
//        }
        return this.packGetInfo(orders, null, false, splitList.getExistCodes(), new JSONObject(), interfaceEnum, logSign, venderId);
    }

    /**
     * 通过发货单ID获取返仓单明细信息
     *
     * @param codes
     * @param interfaceEnum
     * @param logSign
     * @return
     */
    @Transactional(readOnly = true)
    public JSONObject getReturnDetailsByDeliveryIds(List<Long> codes, InterfaceEnum interfaceEnum, String logSign, Long venderid) {
        List<Map<String, Object>> orders = findOrderByMisDao.getReturnInfoByShippingIds(codes);
        FindOrderByMisService.SplitList splitList = this.splitListByIsTms(orders, codes, interfaceEnum, false, logSign, venderid);
        List<Long> existKeys = this.getExistKeys(orders, splitList.getExistCodes(), interfaceEnum);
        List<Map<String, Object>> details;
        if (existKeys.size() > 0) {
            details = findOrderByMisDao.getReturnOrderDetails(existKeys);
        } else {
            details = new ArrayList<>();
        }
//        JSONObject returnObject;
//        if (!this.isTmsNull(splitList.getTmsContent())) {
//            returnObject = JSONObject.parseObject(splitList.getTmsContent());
//        } else {
//            returnObject = new JSONObject();
//        }

        JSONObject returnObject = new JSONObject();
        return this.packDetails(orders, details, existKeys, returnObject, interfaceEnum, logSign, venderid);
    }

    /**
     * 通过签收单号和商品名称模糊查询签收单明细
     *
     * @param code
     * @param query
     * @param logSign
     * @return
     */
    @Transactional(readOnly = true)
    public JSONArray getReceiptDetails(Long code, String query, String logSign, Long venderId) throws IOException {
        JSONArray detailsObject = new JSONArray();

        List<Map<String, Object>> details = this.findOrderByMisDao.getReceiptDetails(code, query);
        if (details != null && !details.isEmpty()) {
            for (Map<String, Object> map : details) {
                detailsObject.add(map);
            }
        }
        //TODO 20191226 去掉tms获取
//        } else {
//            HttpMessage httpMessage = this.tmsProxy.getReceiptDetails(code, query, logSign, venderId);
//            String content = TmsProxy.getContent(httpMessage.getMessage());
//            if (!StringUtils.isBlank(content)) {
//                String info = JSONObject.parseObject(content).getString("info");
//                if (!StringUtils.isBlank(info)) {
//                    String detailsString = JSONObject.parseObject(info).getString("detail_list");
//                    if (!StringUtils.isBlank(detailsString)) {
//                        detailsObject = JSONArray.parseArray(detailsString);
//                    } else {
//                        detailsObject = new JSONArray();
//                    }
//                } else {
//                    detailsObject = new JSONArray();
//                }
//            } else {
//                detailsObject = new JSONArray();
//            }
//        }

        return detailsObject;
    }

    /**
     * 通过签收单明细ID获取签收单明细详细信息
     *
     * @param code
     * @param detailCode
     * @param logSign
     * @return
     * @throws IOException
     */
    @Transactional(readOnly = true)
    public JSONObject getReceiptDetailInfo(Long code, Long detailCode, String logSign, Long venderId) throws IOException {
        JSONObject detailObject;

        Map<String, Object> detail = this.findOrderByMisDao.getReceiptDetailInfo(code, detailCode);
        if (detail != null) {
            detailObject = mapToJson(detail);
        } else {
            throw new BusinessException("签收单明细信息不存在");
            //TODO 20191226 此次改版，签收单都由oms生成，取消tms获取
//            HttpMessage httpMessage = this.tmsProxy.getReceiptDetailInfo(code, detailCode, logSign, venderId);
//            String content = TmsProxy.getContent(httpMessage.getMessage());
//            if (StringUtils.isBlank(content)) {
//                throw new BusinessException("签收单明细信息不存在");
//            }
//            String info = JSONObject.parseObject(content).getString("info");
//            if (StringUtils.isBlank(info)) {
//                throw new BusinessException("签收单明细信息不存在");
//            }
//            String detailsString = JSONObject.parseObject(info).getString("detail_list");
//            if (StringUtils.isBlank(detailsString)) {
//                throw new BusinessException("签收单明细信息不存在");
//            }
//            JSONArray array = JSONArray.parseArray(detailsString);
//            if (array == null || array.isEmpty()) {
//                throw new BusinessException("签收单明细信息不存在");
//            }
//            detailObject = array.getJSONObject(0);
        }

        return detailObject;
    }

//    private void fillDeliveryInfo(Map<String, Object> order) {
//        String omsExt = (String) order.get("oms_ext");
//        if (StringUtils.isNotEmpty(omsExt)) {
//            JSONObject omsExtJson = JSON.parseObject(omsExt);
//            JSONObject deliveryInfo = omsExtJson.getJSONObject("deliveryInfo");
//            if (deliveryInfo != null && deliveryInfo.size() != 0) {
//                String trans_name = deliveryInfo.getString("deliveryName");
//                String trans_cellphone = deliveryInfo.getString("deliveryPhone");
//                order.put("trans_name", trans_name == null ? "" : trans_name);
//                order.put("trans_cellphone", trans_cellphone == null ? "" : trans_cellphone);
//            }
//        }
//    }

    private void fillReceiptStatus(Map<String, Object> order, boolean isSelect, Long code) {
        if (order == null) {
            return;
        }

        Object receiptStatus = null;
        if (isSelect) {
            Map<String, Object> receiptOrder = findOrderByMisDao.getReceiptByDeliveryId(code);
            if (receiptOrder != null) {
                receiptStatus = receiptOrder.get("status");
            }
        } else {
            receiptStatus = order.get("status");
        }

        //TODO
        order.put("receipt_status", receiptStatus == null ? "0" : receiptStatus);
    }

    private SplitList splitListByIsTms(List<Map<String, Object>> orders, List<Long> codes, InterfaceEnum interfaceEnum, Boolean isRequestTms, String logSign, Long venderId) {
        Set<Long> existCodes = new HashSet<>();
        Set<Long> notExistCodes = new HashSet<>();

        for (Map<String, Object> order : orders) {
            Long code = Long.valueOf(String.valueOf(order.get(interfaceEnum.getSelectColumn())));
            existCodes.add(code);
        }

        return this.newSplitList(existCodes, notExistCodes);
    }

    private JSONObject packGetInfo(List<Map<String, Object>> orders, List<Map<String, Object>> details, Boolean isHaveDetail,
                                   Set<Long> existCodes, JSONObject returnObject, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        if (orders != null && orders.size() > 0) {
            for (Map<String, Object> order : orders) {
                Long selectCode = Long.valueOf(String.valueOf(order.get(interfaceEnum.getSelectColumn())));
                if (existCodes.contains(selectCode)) {
                    JSONObject existOrder;
                    if (isHaveDetail) {
                        existOrder = new JSONObject();
                        JSONObject orderObject = this.mapToJson(order);
                        existOrder.put("head", orderObject);

                        Long code = Long.valueOf(String.valueOf(order.get(interfaceEnum.getCodeColumn())));
                        JSONArray existDetails = new JSONArray();
//                        logger.info("pikInfo  details size " + details.size());
                        if (details != null && details.size() > 0) {
                            Iterator iterator = details.iterator();
                            while (iterator.hasNext()) {
                                Map<String, Object> detail = (Map<String, Object>) iterator.next();
                                Long detailCode = Long.valueOf(String.valueOf(detail.get(interfaceEnum.getCodeColumn())));
                                if (code.compareTo(detailCode) == 0) {
                                    JSONObject detailObject = new JSONObject(detail);
                                    setExtToDetail(detailObject);
                                    existDetails.add(detailObject);
                                    iterator.remove();
                                    logger.info("pikInfo  details size delete " + detailCode);
                                }
                            }
                        }
                        existOrder.put("detail", existDetails);
                    } else {
                        existOrder = this.mapToJson(order);
                    }

                    returnObject.put(String.valueOf(selectCode), existOrder);
                }
            }
        }

        if (isHaveDetail) {
            if (interfaceEnum.getAssembly()) {
                for (Long code : existCodes) {
                    JSONObject order = returnObject.getJSONObject(code.toString());
                    JSONArray detailArray = order.getJSONArray("detail");

                    LoggerUtils.saveLog(" [PackGetInfo][logSign:" + logSign + "][Order:" + JSON.toJSONString(order) + "]", LoggerConstant.LOGGER_INFO);
                    String orderId = String.valueOf(order.getJSONObject("head").get(ORDER_ID));
                    JSONArray detailsTmp = ComputeServiceUtils.getAssemblyResp(orderId, detailArray, logSign, assemblyUrl, venderId);
                    if (detailsTmp != null) {
                        order.put("detail", detailsTmp);
                    }
                }
            }
        }

        return returnObject;
    }

    private List<JSONObject> packList(List<Map<String, Object>> orders, List<Long> codes,
                                      JSONArray tmsArray, InterfaceEnum interfaceEnum, String logSign) {
        Map<Long, JSONObject> orderMap = new HashMap<>();

        Iterator<Object> iterator = tmsArray.iterator();
        while (iterator.hasNext()) {
            Object object = iterator.next();
            if (object instanceof JSONArray) {
                continue;
            }
            JSONObject jsonObject = (JSONObject) object;
            Long code = Long.valueOf(String.valueOf(jsonObject.get(interfaceEnum.getSelectColumn())));
            orderMap.put(code, jsonObject);
        }

        for (Map<String, Object> map : orders) {
            Long code = Long.valueOf(String.valueOf(map.get(interfaceEnum.getSelectColumn())));
            if (orderMap.containsKey(code)) {
                continue;
            }
            JSONObject jsonObject = this.mapToJson(map);
            orderMap.put(code, jsonObject);
        }

        List<JSONObject> orderList = new ArrayList<>();
        for (Long code : codes) {
            if (orderMap.get(code) == null) {
                continue;
            }
            orderList.add(orderMap.get(code));
        }

        return orderList;
    }

    private Object getOrderType(Long orderCode) {

        Integer orderType = 0;


        Optional<OrderSignHead> orderSignHeadOptional = signService.findByOrderId(orderCode, false);

        Criteria criteria = new Criteria();
        criteria.add("order_id", orderCode + "");
        criteria.add("occasion", "BEFORE_SIGN");
        Pageable<Return> result = returns.query(criteria, 1L, 10L);

        Long size = result.getTotalCount();
        if (orderSignHeadOptional.isPresent() && size >= 1) {
            orderType = 3;
        } else if (orderSignHeadOptional.isPresent()) {
            orderType = 1;
        } else if (size >= 1) {
            orderType = 2;
        }

        return orderType;
    }


    private JSONObject packOrder(Map<String, Object> order, List<Map<String, Object>> details,
                                 InterfaceEnum interfaceEnum, Boolean isDetail, String logSign, FindOrderByMisDao findOrderByMisDao, Long venderId) {
        LoggerUtils.saveLog(" [PackOrder][logSign:" + logSign + "][Order:" + JSON.toJSONString(order) + "]", LoggerConstant.LOGGER_INFO);

        JSONObject headInfo = null;
        if (order != null && StringUtils.isNotEmpty(String.valueOf(order.get(TMS_EXT)))
                && interfaceEnum.getTmsConfig().getIndex() != TmsConfig.RETURN.getIndex()) {
            try {
                JSONObject json = JSONObject.parseObject(String.valueOf(order.get(TMS_EXT)));
                if (!StringUtils.isBlank(json.getString(HEAD_INFO))) {
                    headInfo = JSONObject.parseObject(json.getString(HEAD_INFO));
                }

                Object ext = order.get(TMS_EXT);
                if (ext != null) {
                    JSONObject extJson = JSON.parseObject(ext.toString());
                    JSONObject proofInfo = extJson.getJSONObject("proof_info");
                    JSONArray imgListAll = new JSONArray();
                    if (proofInfo != null) {
                        JSONArray imgList = proofInfo.getJSONArray("img_list");

                        imgListAll.addAll(imgList);
                    }


                    Object orderId = order.get("order_id");
                    if (orderId != null) {
                        BigInteger orderCode = (BigInteger) orderId;
                        Map<String, Object> deliveryOrder = findOrderByMisDao.getDeliveryByOrderId(orderCode.longValue());
                        if (null != deliveryOrder) {
                            JSONObject deliveryExtJson = JSONObject.parseObject(String.valueOf(deliveryOrder.get("oms_ext")));
                            if (null != deliveryExtJson) {
                                proofInfo = deliveryExtJson.getJSONObject("proof_info");

                                if (proofInfo != null) {
                                    JSONArray imgList = proofInfo.getJSONArray("img_list");

                                    imgListAll.addAll(imgList);
                                }
                            }
                        }
                    }


//                    if (null == proofInfo) {
//                        Object orderId = order.get("order_id");
//                        if (orderId != null) {
//                            BigInteger orderCode = (BigInteger) orderId;
//                            Map<String, Object> returnOrder = findOrderByMisDao.getReturnByOrderId(orderCode.longValue());
//                            if (null != returnOrder) {
//                                JSONObject returnExtJson = JSONObject.parseObject(String.valueOf(returnOrder.get("ext")));
//                                if (null != returnExtJson) {
//                                    proofInfo = returnExtJson.getJSONObject("proof_info");
//                                }
//                            }
//                        }
//                    }

//                    logger.info("bill proofInfo is " + proofInfo);
//                    if (proofInfo != null) {
//                        JSONArray imgList = proofInfo.getJSONArray("img_list");

                    if (imgListAll != null) {
                        for (int i = 0; i < imgListAll.size(); i++) {
                            JSONObject imgJson = new JSONObject();
                            String imgId = imgListAll.getString(i);

                            imgJson.put("id", imgId);
                            imgJson.put("large", imgHost + imgId + "@!common_large");
                            imgJson.put("medium", imgHost + imgId + "@!common_medium");
                            imgJson.put("small", imgHost + imgId + "@!common_small");
                            imgJson.put("tiny", imgHost + imgId + "@!common_tiny");
                            imgJson.put("origin", imgHost + imgId);

                            imgListAll.set(i, imgJson);
                        }

                        if (proofInfo == null) {

                            proofInfo = new JSONObject();
                        }

                        proofInfo.put("img_list", imgListAll);
                        extJson.put("proof_info", proofInfo);

                        order.put(TMS_EXT, extJson.toJSONString());
                    }
                }

            } catch (Exception e) {
                logger.error(" [PackOrder][logSign:" + logSign + "]", e);
                e.printStackTrace();
                headInfo = this.mapToJson(order);
            }
        } else {
            headInfo = this.mapToJson(order);
        }


        if (headInfo != null && !headInfo.containsKey("pay_coupon_money")) {
            //TODO:
            headInfo.put("pay_coupon_money", "0.00");
        }
        setExtToDetails(details);

        JSONArray detailArray = null;
        if (interfaceEnum.getAssembly()) {
            if (order != null && !StringUtils.isBlank(String.valueOf(order.get(ORDER_ID))) && details != null && details.size() > 0) {
                String orderId = String.valueOf(order.get(ORDER_ID));
                String detailString = JSON.toJSONString(details);
                detailArray = ComputeServiceUtils.getAssemblyResp(orderId, JSONArray.parseArray(detailString), logSign, assemblyUrl, venderId);
            }
        }

        //TODO
//        if (interfaceEnum == InterfaceEnum.RETURN_DETAIL) {
//            if (order != null) {
//                String warehouseId = null;
//                if (order.get("warehouse_id") != null
//                        && !StringUtils.isBlank(String.valueOf(order.get("warehouse_id")))) {
//                    warehouseId = String.valueOf(order.get("warehouse_id"));
//                }
//                if (interfaceEnum.getAssembly() && detailArray != null) {
//                    Iterator iterator = detailArray.iterator();
//                    while (iterator.hasNext()) {
//                        Object object = iterator.next();
//                        JSONObject detail = (JSONObject) object;
//                        detail.put("warehouse_id", warehouseId);
//                        detail.put("price", "0.00");
//                    }
//                } else {
//                    for (Map<String, Object> detail : details) {
//                        detail.put("warehouse_id", warehouseId);
//                        detail.put("price", "0.00");
//                    }
//                }
//
//                headInfo.put("money", "0.00");
//            }
//        }

        JSONArray orderList = new JSONArray();
        JSONObject orderObject = new JSONObject();
        orderObject.put("head_info", headInfo);
        if (detailArray == null) {
            orderObject.put("detail_list", details);
        } else {
            orderObject.put("detail_list", detailArray);
        }
        orderList.add(orderObject);

        JSONObject returnObject = new JSONObject();
        returnObject.put("order_info", this.mapToJson2(order));
        returnObject.put("order_list", orderList);

        // TODO 配置优化 新建字典表
        if (isDetail) {

            JSONObject config = ConfigBuilder.getConfig(interfaceEnum);

            JSONArray relateOrders = new JSONArray();
            if (order != null && !StringUtils.isBlank(String.valueOf(order.get(ORDER_ID)))) {
                Long orderId = Long.valueOf(String.valueOf(order.get(ORDER_ID)));

                MisOrderHeadForDetail misOrderHeadForDetail = findOrderByMisDao.getOrderHead(orderId);
                if (misOrderHeadForDetail != null) {
                    JSONObject relateOrder = new JSONObject();
                    relateOrder.put("status_name", OrderStatus.getName(misOrderHeadForDetail.getOrderStatus()));
                    relateOrder.put("ordered_at", misOrderHeadForDetail.getOrderTime());
                    relateOrder.put("order_id", misOrderHeadForDetail.getOrderCode());
                    relateOrder.put("type", "1");
                    relateOrders.add(relateOrder);
                }

                Map<String, Object> receiptOrder, returnOrder, shippingOrder;
                switch (interfaceEnum.getIndex()) {
                    case 6:
                        receiptOrder = findOrderByMisDao.getReceiptByOrderId(orderId);
                        this.getReceiptOrder4Relate(relateOrders, receiptOrder);
//                        returnOrder = findOrderByMisDao.getReturnByOrderId(orderId);
//                        this.getReturnOrder4Relate(relateOrders, returnOrder);
                        break;
                    case 7:
                        shippingOrder = findOrderByMisDao.getDeliveryByOrderId(orderId);
                        this.getShippingOrder4Relate(relateOrders, shippingOrder);
//                        returnOrder = findOrderByMisDao.getReturnByOrderId(orderId);
//                        this.getReturnOrder4Relate(relateOrders, returnOrder);
                        break;
                    case 8:
                        shippingOrder = findOrderByMisDao.getDeliveryByOrderId(orderId);
                        this.getShippingOrder4Relate(relateOrders, shippingOrder);
                        receiptOrder = findOrderByMisDao.getReceiptByOrderId(orderId);
                        this.getReceiptOrder4Relate(relateOrders, receiptOrder);
                        break;
                }
            }

            returnObject.put("config", config);
            returnObject.put("related_order", relateOrders);
            returnObject.put("position_info", null);
            returnObject.put("afs_order", new JSONArray());
        }

        return returnObject;
    }

//    private JSONObject getConfig(InterfaceEnum interfaceEnum) {
//
//        JSONObject config = new JSONObject();
//
//        Integer index = interfaceEnum.getTmsConfig().getIndex();
//
//        if (index == 2) {
//
//            JSONObject orderStatusJson = new JSONObject(true);
//            for (ShippingStatus orderStatus : ShippingStatus.values()) {
//                orderStatusJson.put(String.valueOf(orderStatus.getIndex()), orderStatus.getName());
//            }
//
//            JSONObject orderTypeJson = new JSONObject(true);
//            for (MisOrderType orderType : MisOrderType.values()) {
//                orderStatusJson.put(String.valueOf(orderType.getCode()), orderType.getName());
//            }
//
//            JSONObject delayTypeJson = new JSONObject(true);
//            for (DelayType delayType : DelayType.values()) {
//                delayTypeJson.put(String.valueOf(delayType.getIndex()), delayType.getDesc());
//            }
//
//            config.put("order_status", orderStatusJson);
//            config.put("order_type", orderTypeJson);
//            config.put("delay_type", delayTypeJson);
//        }
//
//        if (index == 3) {
//
//            JSONObject orderStatusJson = new JSONObject(true);
//            for (SignStatus orderStatus : SignStatus.values()) {
//                orderStatusJson.put(String.valueOf(orderStatus.getIndex()), orderStatus.getName());
//            }
//
//            JSONObject payTypeJson = new JSONObject(true);
//            for (PayChannel payChannel : PayChannel.values()) {
//                payTypeJson.put(String.valueOf(payChannel.getIndex()), payChannel.getName());
//            }
//
//            JSONObject orderTypeJson = new JSONObject(true);
//            for (MisOrderType orderType : MisOrderType.values()) {
//                orderTypeJson.put(String.valueOf(orderType.getCode()), orderType.getName());
//            }
//
//            JSONObject payStatusJson = new JSONObject(true);
//            for (PayStatus payStatus : PayStatus.values()) {
//                payStatusJson.put(String.valueOf(payStatus.getValue()), payStatus.getDesc());
//            }
//
//
//            JSONObject statusMemoJson = new JSONObject(true);
//            for (StatusMemo payStatus : StatusMemo.values()) {
//                statusMemoJson.put(String.valueOf(payStatus.getCode()), payStatus.getName());
//            }
//
//            config.put("order_status", orderStatusJson);
//            config.put("pay_type", payTypeJson);
//            config.put("order_type", orderTypeJson);
//            config.put("pay_status", payStatusJson);
//            config.put("status_memo", statusMemoJson);
//        }
//
//        if (index == 4) {
//            JSONObject orderStatusJson = new JSONObject(true);
//            for (ReturnStatus orderStatus : ReturnStatus.values()) {
//                orderStatusJson.put(String.valueOf(orderStatus.getIndex()), orderStatus.getName());
//            }
//
//            JSONObject orderTypeJson = new JSONObject(true);
//            for (MisOrderType orderType : MisOrderType.values()) {
//                orderTypeJson.put(String.valueOf(orderType.getCode()), orderType.getName());
//            }
//
//            JSONObject returnTypeJson = new JSONObject(true);
//            for (ReturnType orderType : ReturnType.values()) {
//                returnTypeJson.put(String.valueOf(orderType.getIndex()), orderType.getName());
//            }
//
//            JSONObject returnOrderTypeJson = new JSONObject(true);
//            for (ReturnOrderType orderType : ReturnOrderType.values()) {
//                returnOrderTypeJson.put(String.valueOf(orderType.getIndex()), orderType.getName());
//            }
//
//            config.put("order_status", orderStatusJson);
//            config.put("return_type", returnTypeJson);
//            config.put("order_type", orderTypeJson);
//            config.put("return_order_type", returnOrderTypeJson);
//        }
//
//        return config;
//    }


    private JSONObject packDetails(List<Map<String, Object>> orders, List<Map<String, Object>> details,
                                   List<Long> existKeys, JSONObject returnObject, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
        Map<Long, String> keyCode = new HashMap<>();
        Map<Long, String> orderIdMap = new HashMap<>();
        for (Map<String, Object> order : orders) {
            Long key = Long.valueOf(String.valueOf(order.get(interfaceEnum.getCodeColumn())));
            String code = String.valueOf(order.get(interfaceEnum.getSelectColumn()));
            String orderId = String.valueOf(order.get(ORDER_ID));
            keyCode.put(key, code);
            orderIdMap.put(key, orderId);
        }

        Map<Long, JSONArray> detailsMap = new HashMap<>();
        Iterator iterator = details.iterator();
        while (iterator.hasNext()) {
            Object object = iterator.next();
            Map<String, Object> detail = (Map<String, Object>) object;
            Long key = Long.valueOf(String.valueOf(detail.get(interfaceEnum.getCodeColumn())));

            JSONArray detailArray = detailsMap.get(key);
            if (detailArray == null) {
                detailArray = new JSONArray();
                JSONObject jsonObject = this.mapToJson(detail);
                detailArray.add(jsonObject);

                detailsMap.put(key, detailArray);
            } else {
                JSONObject jsonObject = this.mapToJson(detail);
                detailArray.add(jsonObject);
            }
        }

        for (Long key : existKeys) {
            if (keyCode.containsKey(key) && detailsMap.get(key) != null) {
                String code = keyCode.get(key);
                JSONArray detailArray = detailsMap.get(key);
                setExtToDetails(detailArray);
                if (interfaceEnum.getAssembly()) {
                    String orderId = orderIdMap.get(key);
                    LoggerUtils.saveLog(" [PackDetails][logSign:" + logSign + "][Order:" + orderId + "]", LoggerConstant.LOGGER_INFO);
                    JSONArray detailsTmp = ComputeServiceUtils.getAssemblyResp(orderId, detailArray, logSign, assemblyUrl, venderId);

                    if (detailsTmp != null) {
                        returnObject.put(code, detailsTmp);
                    } else {
                        returnObject.put(code, detailArray);
                    }
                } else {
                    returnObject.put(code, detailArray);
                }
            }
        }

        return returnObject;
    }

//    private SplitList getTmsContentByCodes(Set<Long> existCodes, Set<Long> notExistCodes, InterfaceEnum interfaceEnum,
//                                           String logSign, Long venderId) {
//        String url = this.getUrl(this.tmsHost, interfaceEnum.getUrl(), interfaceEnum.getParam(), JSON.toJSONString(notExistCodes));
//        String returnMessage = null;
//        Long tmsLogSign = IdGenerator.genId();
//        HttpMessage httpMessage;
//        try {
//            LoggerUtils.saveLog(" [SplitListByIsTms][logSign:" + logSign + "][TmsLogSign:" + tmsLogSign + "][url:" + url + "]",
//                    LoggerConstant.LOGGER_INFO);
//            httpMessage = HttpUtils.sendGetRequest(url, ToolService.getRequestTmsHeader(tmsLogSign, venderId));
//            LoggerUtils.saveLog(" [SplitListByIsTms][logSign:" + logSign + "][return status:" + httpMessage.getStatus() + "]",
//                    LoggerConstant.LOGGER_INFO);
//            tmsLog.info(" [SplitListByIsTms][logSign:" + logSign + "][return message:" + httpMessage.getMessage() + "]");
//
//            if (BaseProxy.isSuccess(httpMessage.getMessage())) {
//                returnMessage = BaseProxy.getContent(httpMessage.getMessage());
//            }
//        } catch (IOException e) {
//            LoggerUtils.saveLog(" [SplitListByIsTms][logSign:" + logSign + "][Error Class : " + e.getClass()
//                            + ", Error Message : " + e.getMessage() + "]",
//                    LoggerConstant.LOGGER_ERROR);
//            logger.error(e.getMessage(), e);
//        } catch (JSONException e) {
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][Error Class : " + e.getClass()
//                            + ", Error Message : " + e.getMessage() + "]",
//                    LoggerConstant.LOGGER_ERROR);
//            logger.error(e.getMessage(), e);
//        }
//
////        return this.newSplitList(existCodes, notExistCodes, returnMessage);
//
//        return this.newSplitList(existCodes, notExistCodes);
//    }

//    private String getTmsContentByCode(Long code, InterfaceEnum interfaceEnum, Long venderId, String logSign) {
//        String url = this.getUrl(this.tmsHost, interfaceEnum.getUrl(), interfaceEnum.getParam(), code);
//
//        String returnMessage = null;
//
//        Long tmsLogSign = IdGenerator.genId();
//        HttpMessage httpMessage;
//        try {
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][TmsLogSign:" + tmsLogSign + "][url:" + url + "]", LoggerConstant.LOGGER_INFO);
//            httpMessage = HttpUtils.sendGetRequest(url, ToolService.getRequestTmsHeader(tmsLogSign, venderId));
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][return status:" + httpMessage.getStatus() + "][return message:" + httpMessage.getMessage() + "]", LoggerConstant.LOGGER_INFO);
//            tmsLog.info(" [GetTmsContentByCode][logSign:" + logSign + "][return message:" + httpMessage.getMessage() + "]");
//
//            if (StringUtils.isBlank(httpMessage.getMessage()) || !(httpMessage.getMessage().startsWith("{"))) {
//                return null;
//            }
//            if (BaseProxy.isSuccess(httpMessage.getMessage())) {
//                returnMessage = BaseProxy.getContent(httpMessage.getMessage());
//            }
//        } catch (IOException e) {
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][Error Class : " + e.getClass()
//                            + ", Error Message : " + e.getMessage() + "]",
//                    LoggerConstant.LOGGER_ERROR);
//            logger.error(e.getMessage(), e);
//        } catch (JSONException e) {
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][Error Class : " + e.getClass()
//                            + ", Error Message : " + e.getMessage() + "]",
//                    LoggerConstant.LOGGER_ERROR);
//            logger.error(e.getMessage(), e);
//        }
//
//        return returnMessage;
//    }
//
//    private String getTmsContentByCode2(Long code, InterfaceEnum interfaceEnum, String logSign, Long venderId) {
//        String url = this.getUrl2(this.tmsHost, interfaceEnum.getUrl(), interfaceEnum.getParam(), code, 2);
//
//        String returnMessage = null;
//
//        Long tmsLogSign = IdGenerator.genId();
//        HttpMessage httpMessage;
//        try {
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][TmsLogSign:" + tmsLogSign + "][url:" + url + "]", LoggerConstant.LOGGER_INFO);
//            httpMessage = HttpUtils.sendGetRequest(url, ToolService.getRequestTmsHeader(tmsLogSign, venderId));
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][return status:" + httpMessage.getStatus() + "][return message:" + httpMessage.getMessage() + "]", LoggerConstant.LOGGER_INFO);
//            tmsLog.info(" [GetTmsContentByCode][logSign:" + logSign + "][return message:" + httpMessage.getMessage() + "]");
//
//            if (StringUtils.isBlank(httpMessage.getMessage()) || !(httpMessage.getMessage().startsWith("{"))) {
//                return null;
//            }
//            if (BaseProxy.isSuccess(httpMessage.getMessage())) {
//                returnMessage = BaseProxy.getContent(httpMessage.getMessage());
//            }
//        } catch (IOException e) {
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][Error Class : " + e.getClass()
//                            + ", Error Message : " + e.getMessage() + "]",
//                    LoggerConstant.LOGGER_ERROR);
//            logger.error(e.getMessage(), e);
//        } catch (JSONException e) {
//            LoggerUtils.saveLog(" [GetTmsContentByCode][logSign:" + logSign + "][Error Class : " + e.getClass()
//                            + ", Error Message : " + e.getMessage() + "]",
//                    LoggerConstant.LOGGER_ERROR);
//            logger.error(e.getMessage(), e);
//        }
//
//        return returnMessage;
//    }
//
//    private Boolean isTmsOrder(Map<String, Object> map) {
////        if (map == null) {
////            return true;
////        }
////        if (Long.valueOf(String.valueOf(map.get(IS_TMS))).compareTo(0L) <= 0) {
////            return false;
////        } else {
////            return true;
////        }
//
//        return false;
//    }

    private class SplitList {
        private Set<Long> existCodes;
        private Set<Long> notExistCodes;
//        private String tmsContent;

        public SplitList(Set<Long> existCodes, Set<Long> notExistCodes) {
            this.existCodes = existCodes;
            this.notExistCodes = notExistCodes;
//            this.tmsContent = tmsContent;
        }

        public Set<Long> getExistCodes() {
            return existCodes;
        }

        public void setExistCodes(Set<Long> existCodes) {
            this.existCodes = existCodes;
        }

        public Set<Long> getNotExistCodes() {
            return notExistCodes;
        }

        public void setNotExistCodes(Set<Long> notExistCodes) {
            this.notExistCodes = notExistCodes;
        }

//        public String getTmsContent() {
//            return tmsContent;
//        }
//
//        public void setTmsContent(String tmsContent) {
//            this.tmsContent = tmsContent;
//        }

    }

}
